﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
using System.ComponentModel;

namespace Citi.Helpers.Extensions
{
    public static class DataTableExtensions
    {
        public static List<T> ToModel<T>(this DataTable dataTable)
        {
            var models = new List<T>();

            try
            {
                models.AddRange(from DataRow dataRow in dataTable.Rows select (T)ToModel(typeof(T), dataTable, dataRow)[0]);

                return models;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private static List<object> ToModel(Type type, DataTable dataTable, DataRow dataRow)
        {
            Dictionary<string, string> camposDataTable = GetFields(dataTable);
            var models = new List<object>();
            var model = Activator.CreateInstance((type));

            var propriedades = model.GetType().GetProperties();

            foreach (KeyValuePair<string, string> campo in camposDataTable)
            {
                var propriedadeInfo = from propertyInfo in propriedades
                                      where propertyInfo.Name == campo.Value
                                      || propertyInfo.GetCustomAttributes(typeof(DescriptionAttribute), false).Any(x => ((DescriptionAttribute)x).Description == campo.Value)
                                      select propertyInfo;

                if (propriedadeInfo.Count() > 0)
                {
                    PropertyInfo propriedade = propriedadeInfo.First();
                    if (dataRow[campo.Key].ToString() != string.Empty)
                    {
                        if (propriedade.PropertyType.Equals(typeof(Decimal)) || propriedade.PropertyType.Equals(typeof(decimal)))
                            propriedade.SetValue(model, Decimal.Parse(dataRow[campo.Key].ToString()), null);
                        else if (propriedade.PropertyType.Equals(typeof(Boolean)) || propriedade.PropertyType.Equals(typeof(bool)))
                            propriedade.SetValue(model, Boolean.Parse(dataRow[campo.Key].ToString()), null);
                        else
                            propriedade.SetValue(model, dataRow[campo.Key], null);
                    }
                }
            }

            models.Add(model);
            return models;
        }

        private static Dictionary<string, string> GetFields(DataTable dataTable)
        {
            Dictionary<string, string> camposDataTable = new Dictionary<string, string>();

            foreach (DataColumn coluna in dataTable.Columns)
                camposDataTable.Add(coluna.ColumnName, GetModelName(coluna.ColumnName));

            return camposDataTable;
        }

        private static string GetModelName(string columnName)
        {
            return columnName.Replace("ows_ID", "Id").Replace("ows_", string.Empty).Replace("_", string.Empty).Replace(" ", string.Empty);
        }
    }
}
